package com.amoyt.project.service.admin.impl;

import com.amoyt.project.config.redis.RedisCache;
import com.amoyt.project.constants.RedisConstants;
import com.amoyt.project.constants.UserTypeConstants;
import com.amoyt.project.domain.pojo.*;
import com.amoyt.project.domain.res.Result;
import com.amoyt.project.domain.vo.data.*;
import com.amoyt.project.mapper.*;
import com.amoyt.project.service.admin.DataService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Date: 2025/8/28
 * @Time: 0:22
 * @Author: TQ_QT
 * @Description:
 */
@Service
public class DataServiceImpl implements DataService {
    @Autowired
    private PovertyHouseholdBaseMapper householdMapper;
    @Autowired
    private PovertyPersonMapper personMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private ProjectApprovalMapper projectMapper;
    @Autowired
    private FeedbackMapper feedbackMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RedisCache redisCache;

    @Override
    public Result poverty() {

        //0.先查redis
        PovertyDataVo redisData = (PovertyDataVo) redisCache.getCacheObject(RedisConstants.CACHE_POVERTY_DATA);
        if(redisData != null){
            return Result.success(redisData);
        }

        // 1. 统计总贫困户数量和总贫困人员数量
        Long totalHousehold = householdMapper.selectCount(new QueryWrapper<HouseholdBase>());
        Long totalPerson = personMapper.selectCount(new QueryWrapper<PovertyPerson>().eq("is_core", 1));

        // 2. 统计各等级贫困户数据列表
        List<PovertyDataVo.LevelData> levelDataList = new ArrayList<>();

        // 查询所有贫困户等级（去重）
        List<Object> levels = householdMapper.selectObjs(new QueryWrapper<HouseholdBase>()
                .select("DISTINCT poverty_level")
                .isNotNull("poverty_level"));

        for (Object level : levels) {
            String povertyLevel = (String) level;
            // 统计该等级的贫困户数量
            Long levelCount = householdMapper.selectCount(new QueryWrapper<HouseholdBase>()
                    .eq("poverty_level", povertyLevel));

            levelDataList.add(new PovertyDataVo.LevelData(povertyLevel, levelCount));
        }

        // 3. 统计各类型贫困人员数据列表
        List<PovertyDataVo.personData> personDataList = new ArrayList<>();

        // 查询所有贫困类型（去重）
        List<Object> types = personMapper.selectObjs(new QueryWrapper<PovertyPerson>()
                .select("DISTINCT poverty_type")
                .isNotNull("poverty_type")
                .eq("is_core", 1)); // 只统计核心贫困人员

        for (Object type : types) {
            String povertyType = (String) type;
            // 统计该类型的贫困人员数量
            Long personCount = personMapper.selectCount(new QueryWrapper<PovertyPerson>()
                    .eq("poverty_type", povertyType)
                    .eq("is_core", 1));

            personDataList.add(new PovertyDataVo.personData(povertyType, personCount));
        }

        // 4. 组装返回对象
        PovertyDataVo vo = new PovertyDataVo();
        vo.setTotalHouseholdCount(totalHousehold);
        vo.setTotalPersonCount(totalPerson);
        vo.setLevelDataList(levelDataList);
        vo.setPersonDataList(personDataList);

        //5.存入redis
        redisCache.setCacheObject(RedisConstants.CACHE_POVERTY_DATA, vo, RedisConstants.CACHE_DATA_TTL, TimeUnit.MINUTES);

        return Result.success(vo);
    }

    @Override
    public Result userList() {

        //0.先查redis
        AdminDataVo redisData = (AdminDataVo) redisCache.getCacheObject(RedisConstants.CACHE_USER_DATA);
        if(redisData != null){
            return Result.success(redisData);
        }

        // 1. 构建管理员查询条件（userType=0）
        QueryWrapper<User> adminQuery = new QueryWrapper<User>()
                .eq("user_type", UserTypeConstants.ADMIN);

        // 2. 统计管理员性别分布（仅统计userType=0的用户）
        Long maleCount = userMapper.selectCount(adminQuery.clone()
                .eq("sex", "0"));
        Long femaleCount = userMapper.selectCount(adminQuery.clone()
                .eq("sex", "1"));
        Long unknownCount = userMapper.selectCount(adminQuery.clone()
                .eq("sex", "2"));
        Long visitorCount = userMapper.selectCount(new QueryWrapper<User>().eq("user_type", UserTypeConstants.USER));

        // 3. 统计各级管理员角色数量（排除user角色）
        List<AdminDataVo.roleData> roleDataList = new ArrayList<>();

        // 3.1 查询所有非user角色
        List<Role> nonUserRoles = roleMapper.selectList(new QueryWrapper<Role>()
                .ne("role_key", "user"));

        for (Role role : nonUserRoles) {
            String roleName = role.getName();
            // 3.2 查询该角色关联的管理员用户（同时满足角色关联和管理员类型）
            List<Object> userIds = userRoleMapper.selectObjs(new QueryWrapper<UserRole>()
                    .eq("role_id", role.getRoleId())
                    .select("user_id"));

            if (userIds.isEmpty()) {
                roleDataList.add(new AdminDataVo.roleData(roleName, 0L));
                continue;
            }

            // 3.3 过滤出属于管理员的用户（userType=0）
            Long roleCount = userMapper.selectCount(new QueryWrapper<User>()
                    .in("user_id", userIds)
                    .eq("user_type", 0));

            roleDataList.add(new AdminDataVo.roleData(roleName, roleCount));
        }

        // 4. 组装返回结果
        AdminDataVo vo = new AdminDataVo();
        vo.setMaleCount(maleCount);
        vo.setFemaleCount(femaleCount);
        vo.setUnknownCount(unknownCount);
        vo.setLevelDataList(roleDataList);
        vo.setVisitorCount(visitorCount);

        //5.存入redis
        redisCache.setCacheObject(RedisConstants.CACHE_USER_DATA, vo, RedisConstants.CACHE_DATA_TTL, TimeUnit.MINUTES);

        return Result.success(vo);
    }



    @Override
    public Result articleList() {

        //0.先查redis
        ArticleDataVo redisData = (ArticleDataVo) redisCache.getCacheObject(RedisConstants.CACHE_ARTICLE_DATA);
        if(redisData != null){
            return Result.success(redisData);
        }

        // 1. 查询总公告数量
        Long totalCount = articleMapper.selectCount(null);

        // 2. 查询所有不重复的category（明确处理为Integer类型）
        List<Integer> categories = articleMapper.selectObjs(new QueryWrapper<Article>()
                        .select("DISTINCT category")
                        .isNotNull("category"))
                .stream()
                // 安全转换为Integer，处理可能的类型转换问题
                .map(obj -> {
                    if (obj instanceof Number) {
                        return ((Number) obj).intValue();
                    } else {
                        return -1;
                    }
                })
                // 过滤异常值
                .filter(cat -> cat != -1)
                .collect(Collectors.toList());

        // 3. 统计每个类别的公告数量
        List<ArticleDataVo.typeData> typeDataList = new ArrayList<>();
        for (Integer category : categories) {
            // 统计该类别的公告数量
            Long categoryCount = articleMapper.selectCount(new QueryWrapper<Article>()
                    .eq("category", category));

            typeDataList.add(new ArticleDataVo.typeData(category, categoryCount));
        }

        // 4. 处理没有分类数据但有公告的情况
        if (typeDataList.isEmpty() && totalCount > 0) {
            typeDataList.add(new ArticleDataVo.typeData(null, totalCount));
        }

        // 5. 组装返回对象
        ArticleDataVo vo = new ArticleDataVo();
        vo.setTotalCount(totalCount);
        vo.setTypeDataList(typeDataList);

        //6.存入redis
        redisCache.setCacheObject(RedisConstants.CACHE_ARTICLE_DATA, vo, RedisConstants.CACHE_DATA_TTL, TimeUnit.MINUTES);

        return Result.success(vo);
    }



    @Override
    public Result projectList() {

        //0.redis查询
        ProjectDataVo projectDataVo =(ProjectDataVo) redisCache.getCacheObject(RedisConstants.CACHE_PROJECT_DATA);
        if(projectDataVo != null){
            return Result.success(projectDataVo);
        }

        // 1. 查询总项目数量
        Long totalCount = projectMapper.selectCount(null);

        // 2. 查询所有不重复的项目等级
        List<Object> projectLevels = projectMapper.selectObjs(new QueryWrapper<ProjectApproval>()
                .select("DISTINCT project_level")
                .isNotNull("project_level"));

        // 3. 统计各等级项目数量
        List<ProjectDataVo.levelData> levelDataList = new ArrayList<>();
        for (Object level : projectLevels) {
            // 项目等级字段为String类型，直接转换
            String projectLevel = (String) level;

            // 统计该等级的项目数量
            Long projectCount = projectMapper.selectCount(new QueryWrapper<ProjectApproval>()
                    .eq("project_level", projectLevel));

            levelDataList.add(new ProjectDataVo.levelData(projectLevel, projectCount));
        }

        // 4. 处理无等级分类但有项目的情况
        if (levelDataList.isEmpty() && totalCount > 0) {
            levelDataList.add(new ProjectDataVo.levelData("未分类", totalCount));
        }

        // 5. 组装返回对象
        ProjectDataVo vo = new ProjectDataVo();
        vo.setTotalCount(totalCount);
        vo.setLevelDataList(levelDataList); // 注意：需要在ProjectDataVo中添加该字段的setter

        redisCache.setCacheObject(RedisConstants.CACHE_PROJECT_DATA, vo, RedisConstants.CACHE_DATA_TTL, TimeUnit.MINUTES);

        return Result.success(vo);
    }


    @Override
    public Result backList(Integer day) {
        // 校验day参数，设置默认值为7天
        if (day == null || day <= 0) {
            day = 7;
        }

        // 时间格式化器
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime now = LocalDateTime.now();

        // 今日时间范围：今日0点至当前时刻
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime todayEnd = now;

        // 1. 总投诉数量
        Long totalCount = feedbackMapper.selectCount(new QueryWrapper<Feedback>()
                .eq("deleted", 0));

        // 2. 今日投诉数量（0点至当前）
        Long todayCount = feedbackMapper.selectCount(new QueryWrapper<Feedback>()
                .ge("create_time", todayStart)
                .le("create_time", todayEnd)
                .eq("deleted", 0));

        // 3. 待处理投诉数量（is_handle=0）
        Long waitCount = feedbackMapper.selectCount(new QueryWrapper<Feedback>()
                .eq("is_handle", 0)
                .eq("deleted", 0));

        // 4. 近day天投诉统计
        List<FeedBackDataVo.SevenDaysData> daysCount = new ArrayList<>();
        List<LocalDate> recentDays = new ArrayList<>();

        // 生成近day天的日期列表（从day-1天前到今天）
        for (int i = day - 1; i >= 0; i--) {
            recentDays.add(LocalDate.now().minusDays(i));
        }

        // 批量查询近day天数据
        LocalDateTime daysAgoStart = LocalDateTime.of(recentDays.get(0), LocalTime.MIN);
        List<Feedback> recentFeedbacks = feedbackMapper.selectList(new QueryWrapper<Feedback>()
                .ge("create_time", daysAgoStart)
                .le("create_time", todayEnd)
                .eq("deleted", 0)
                .select("create_time"));

        // 分组统计
        if (!CollectionUtils.isEmpty(recentFeedbacks)) {
            var dateCountMap = recentFeedbacks.stream()
                    .collect(Collectors.groupingBy(
                            f -> f.getCreateTime().toLocalDate().format(dateFormatter),
                            Collectors.counting()
                    ));

            for (LocalDate date : recentDays) {
                String dateStr = date.format(dateFormatter);
                // 如果是今天，使用今日统计数，否则使用map中的统计
                Long count = date.isEqual(LocalDate.now()) ?
                        todayCount :
                        dateCountMap.getOrDefault(dateStr, 0L);
                daysCount.add(new FeedBackDataVo.SevenDaysData(dateStr, count));
            }
        } else {
            // 如果没有数据，全部填充0
            for (LocalDate date : recentDays) {
                daysCount.add(new FeedBackDataVo.SevenDaysData(
                        date.format(dateFormatter),
                        0L
                ));
            }
        }

        // 组装返回对象
        FeedBackDataVo vo = new FeedBackDataVo(
                totalCount,
                todayCount,
                waitCount,
                daysCount
        );

        return Result.success(vo);
    }

}
